package main

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/bitly/go-simplejson"
	"github.com/tarm/serial"
	"parking/src/structs"
	"time"
)

func init() {
	LoadConfigInit(configPath, configName)
	led485Init(led485InfoList)
}
func led485Init(led485InfoList []*structs.Led485ConfigStruct) {
	for _, led485ConfigStruct := range led485InfoList { // 遍历配置列表
		key := led485ConfigStruct.GetName() // 获取设备标识符
		// 如果连接存在则不再连接
		if led485ConnMap[key] != nil {
			return
		}
		serialConf := &serial.Config{ // 构造串口配置
			Name:        "/dev/ttyUSB" + key,
			Baud:        led485ConfigStruct.GetBaud(),
			ReadTimeout: time.Second * 10,
		}
		port := led485ConnTask(serialConf) // 执行实际连接
		if port != nil {                   // 连接成功时
			led485ConnMap[key] = port
			logger.Infof("存储485连接 key: %v port: %v", key, port)
		}
	}
}
func handleLed485Message(payloadJson *simplejson.Json) {
	msgId, _ := payloadJson.Get("msgId").String()
	portStr, _ := payloadJson.Get("channel").String()
	led485MessageJsonArray, _ := payloadJson.Get("chn1Data").Array()
	for _, led485MessageJson := range led485MessageJsonArray {
		led485MessageInfo := led485MessageJson.(map[string]interface{})
		writeData := Convert[string](led485MessageInfo["data"])
		//目前每个循环只有一条显示屏消息
		err := led485WriteTask(portStr, writeData)
		if err != nil {
			// 统一错误响应
			deviceRsp := structs.NewDeviceRsp("rs485TransmitRsp", msgId, "error", err.Error())
			payload, _ := json.Marshal(deviceRsp)
			mqttMessage := structs.NewMQTTMessage(topicPublish_server, 0, false, payload)
			mqttSendMessageToServer(mqttMessage)
			logger.Errorf("显示平显示指令执行失败,msgId: %v", msgId)
		} else {
			// 回复消息表示显示成功
			deviceRsp := structs.NewDeviceRsp("rs485TransmitRsp", msgId, "ok", "")
			payload, _ := json.Marshal(deviceRsp)
			mqttMessage := structs.NewMQTTMessage(topicPublish_server, 0, false, payload)
			mqttSendMessageToServer(mqttMessage)
			logger.Infof("显示平显示指令执行成功,msgId: %v", msgId)
		}
	}
}

func handleCameraErrorShows(ledChannel, ledAddress string) {
	cameraErrorShowsMap := errorShows.Camera
	content := cameraErrorShowsMap[ledAddress]
	portStr := ledChannel
	err := led485WriteTask(portStr, content)
	if err != nil {
		logger.Errorf("显示平显示指令(camera)执行失败")
		return
	}
}

func handleDeviceErrorShows(led485InfoList []*structs.Led485ConfigStruct) {
	deviceErrorShowsMap := errorShows.Device
	for _, led485configStruct := range led485InfoList {
		content := deviceErrorShowsMap[led485configStruct.GetAddress()]
		portStr := led485configStruct.GetName()
		err := led485WriteTask(portStr, content)
		if err != nil {
			logger.Errorf("显示平显示指令(devuce)执行失败")
			return
		}
	}
}

func handleServerErrorShows(led485InfoList []*structs.Led485ConfigStruct) {
	serverErrorShowsMap := errorShows.Server
	for _, led485configStruct := range led485InfoList {
		content := serverErrorShowsMap[led485configStruct.GetAddress()]
		portStr := led485configStruct.GetName()
		err := led485WriteTask(portStr, content)
		if err != nil {
			logger.Errorf("显示平显示指令(server)执行失败")
			return
		}
	}
}
func handleLed485MessageInOffLineMod(payloadJson *simplejson.Json) {
	cameraId, _ := payloadJson.Get("devId").String()
	cameraInfoStruct, exists := camerasInfoMap[cameraId]
	ledAddress := cameraInfoStruct.GetLedAddress()
	cameraErrorShowsMap := errorShows.Camera
	content := cameraErrorShowsMap[ledAddress]

	if !exists {
		logger.Errorf("未找到 cameraId 对应的设备信息: %s", cameraId)
		return
	}
	portStr := cameraInfoStruct.GetLedChannel()

	err := led485WriteTask(portStr, content)
	if err != nil {
		logger.Errorf("显示平显示指令(camera)执行失败,cameraId: %v", cameraId)
		return
	}
}

func led485ConnTask(c *serial.Config) *serial.Port {
	time.Sleep(2 * time.Second)     // 初始延时
	port, err := serial.OpenPort(c) // 尝试打开串口
	if err != nil {                 // 连接失败处理
		logger.Errorf("led485端口连接失败,Error: %v ,Name: %v,Baud: %v ", err, c.Name, c.Baud)
		return nil
	}

	// 发送验证指令
	decodedData, _ := hex.DecodeString("设备连接成功")
	if _, err = port.Write(decodedData); err != nil {
		port.Close() // 关闭无效连接
		logger.Errorf("握手失败 | 设备: %s", c.Name)
		return nil
	}

	logger.Infof("led485连接成功,Name: %v,Baud: %v", c.Name, c.Baud)
	return port // 返回有效连接对象
}

func led485WriteTask(portStr string, data string) error {
	port := led485ConnMap[portStr]
	if port == nil {
		err := fmt.Errorf("led485显示器连接不存在,portNum: %s", portStr)
		logger.Error(err.Error())
		return err
	}

	decodedData, err := hex.DecodeString(data)
	if err != nil {
		err = fmt.Errorf("数据格式错误: %s", data)
		logger.Errorf(err.Error())
		return err
	}

	n, err := port.Write(decodedData)
	if err != nil {
		err = fmt.Errorf("串口数据写入失败: %s (错误详情: %v)", portStr, err)
		logger.Error(err.Error())
		return err
	}

	// 增加硬件状态切换延时（根据RS485规范:ml-citation{ref="4,7" data="citationList"}）
	time.Sleep(10 * time.Millisecond)

	logger.Debugf("Wrote %d bytes to port %s", n, portStr)
	return nil
}

func led485ReadTask(portStr string) []byte {
	var readData []byte
	port := led485ConnMap[portStr]
	if port == nil {
		logger.Error("led485显示器连接不存在,读取失败")
		return nil
	}
	n, err := port.Read(readData)
	if err != nil || n <= 0 {
		logger.Errorf("Failed to read from port: %v", err)
		return nil
	}
	logger.Debugf("Read %d bytes from port %s", n, portStr)
	return readData
}

//var portMutex sync.RWMutex
//for _, led485ConfigStruct := range led485InfoList { // 遍历配置列表
//	key := led485ConfigStruct.GetName() // 获取设备标识符
//	serialConf := &serial.Config{       // 构造串口配置
//		Name:        key, //"/dev/ttyUSB" + key
//		Baud:        led485ConfigStruct.GetBaud(),
//		ReadTimeout: time.Second * 10,
//	}
//
//	// 启动连接守护协程
//	go func(cfg *serial.Config) {
//		defer func() { // 异常恢复机制
//			if err := recover(); err != nil {
//				logger.Error("协程异常退出:", err)
//			}
//		}()
//
//		for { // 无限循环维持连接
//			port := led485ConnTask(cfg) // 执行实际连接
//			if port != nil {            // 连接成功时
//				func() { // 使用闭包限制锁作用域
//					portMutex.Lock()
//					defer portMutex.Unlock()
//					led485ConnMap[key] = port // 存储连接实例
//					logger.Infof("存储485连接 key: %v port: %v", key, port)
//				}()
//
//				// 阻塞等待连接断开
//				<-waitPortClose(port)
//			}
//			time.Sleep(3 * time.Second) // 重试间隔
//		}
//	}(serialConf) // 传入当前循环的配置
//}

// 连接状态检查函数
func waitPortClose(port *serial.Port) <-chan struct{} {
	ch := make(chan struct{}) // 创建状态通道
	go func() {               // 启动监控协程
		buf := make([]byte, 1)
		for {
			_, err := port.Read(buf) // 阻塞读取操作
			if err != nil {          // 发生读取错误
				close(ch) // 关闭通道通知连接断开
				return    // 结束监控协程
			}
		}
	}()
	return ch // 返回通道供主流程监听
}
